package com.gadgets.busi.dataanalysis.registry.task;

import com.gadgets.busi.bm02.common.GadgetsBm02Constant;
import com.gadgets.busi.bm02.common.GadgetsBm02Utils;
import com.gadgets.busi.bm02.dto.RecipeWeightQueryDTO;
import com.gadgets.busi.bm02.pojo.MaterialDict;
import com.gadgets.busi.bm02.pojo.MaterialRecipe;
import com.gadgets.busi.bm02.service.IMaterialAnalysisService;
import com.gadgets.framework.common.constant.GadgetsConstant;
import com.gadgets.framework.common.util.StringUtils;
import com.gadgets.framework.thread.task.AbstractRunnable;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author UncleXiu
 * @version V1.0.0
 * @data 2020-12-02
 *
 */
public class DataAnalysisSeekRunnable extends AbstractRunnable {

    public DataAnalysisSeekRunnable(GadgetsBm02Utils gadgetsBm02Utils, IMaterialAnalysisService materialAnalysisService) {
        setModuelNo(GadgetsBm02Constant.DA_MODUEL_NO);
        this.gadgetsBm02Utils = gadgetsBm02Utils;
        this.materialAnalysisService = materialAnalysisService;
    }

    /**
     * 待分析数据
     */
    private final HashMap<Long, HashMap<String, List<MaterialRecipe>>> workContainer = new HashMap<>();
    /**
     * 分析结果数据集
     */
    private final ConcurrentHashMap<Long, List<MaterialRecipe>> resultContainer = new ConcurrentHashMap<>();
    /**
     * 原料列表
     */
    private final ArrayList<MaterialDict> materialDictArrayList = new ArrayList<>();
    /**
     * 字典工具
     */
    private final GadgetsBm02Utils gadgetsBm02Utils;
    /**
     * 合成表权值计算逻辑类
     */
    private final IMaterialAnalysisService materialAnalysisService;
    /**
     * 合成表查询对象
     */
    private final RecipeWeightQueryDTO queryDto = new RecipeWeightQueryDTO();

    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see Thread#run()
     */
    @Override
    public void run() {
        try {
            for (Map.Entry<Long, HashMap<String, List<MaterialRecipe>>> workEntry : workContainer.entrySet()) {
                MaterialDict materdict = gadgetsBm02Utils.getMcMeterialDictItem(workEntry.getKey());
                if(GadgetsConstant.NUMBER_CONSTANT.STR_NUMBER_0.equals(materdict.getOriFlag())) {
                    logger.debug("开始分析物品{}最优合成表", materdict.getDictName());
                    HashMap<String, List<MaterialRecipe>> recipeMap = workEntry.getValue();
                    double minWeight = Double.MAX_VALUE;
                    // 遍历物品合成表
                    for (Map.Entry<String, List<MaterialRecipe>> recipes : recipeMap.entrySet()) {
                        List<MaterialRecipe> target = recipes.getValue();
                        String batchNo = recipes.getKey();
                        try {
                            // 计算当前合成表权值
                            double currentWeight = recipeWeightModuel(target);
                            // 如果当前合成表权值更低，则说明合成更便利，用当前合成表替换原合成表
                            if (currentWeight < minWeight) {
                                resultContainer.put(workEntry.getKey(), target);
                            }
                            // 设置最小权值为当前权
                            minWeight = Math.min(currentWeight, minWeight);
                            logger.debug("物品{}的合成表{}解析成功", materdict.getDictName(), batchNo);
                        } catch (IOException e) {
                            logger.error("物品{}的合成表{}解析失败", materdict.getDictName(), batchNo);
                            logger.error(StringUtils.formatExceptionStack(e));
                        }
                    }
                    // 将所有合成表的最小合成权作为物品的合成权并更新到缓存中
                    materdict.setWeight(minWeight);
                    materialDictArrayList.add(materdict);
                    gadgetsBm02Utils.addMcMeterialDictItem(materdict);
                }else {
                    logger.debug("物品{}是原始物品，无需分析合成权值",materdict.getDictName());
                }
            }
            taskFinish();
        } catch (Exception exception) {
            logger.error(StringUtils.formatExceptionStack(exception));
            setStatus(1);
        }
    }

    /**
     * 合成表权值计算模型
     * @param recipeList    合成表信息
     * @return              应答信息
     */
    protected Double recipeWeightModuel(List<MaterialRecipe> recipeList) throws IOException {
        return materialAnalysisService.recipeWeightModuel(recipeList);
    }

    /**
     * 增加线程任务
     * @param workContainer 待分析数据任务列表
     */
    public void addWorkList(Map.Entry<Long, HashMap<String, List<MaterialRecipe>>> workContainer){
        this.workContainer.put(workContainer.getKey(),workContainer.getValue());
    }

    public ConcurrentHashMap<Long, List<MaterialRecipe>> getResultContainer() {
        return resultContainer;
    }

    public ArrayList<MaterialDict> getMaterialDictArrayList() {
        return materialDictArrayList;
    }
}
